package com.example.testdraw.charts;

import java.util.logging.Level;
import java.util.logging.Logger;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Handler;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;


public class PieChart extends View {
	private Paint mPaints;
	private RectF oval = null;
	private float[] mSweeps = null;
	public static final int COLORRANGE = Color.BLACK;
	final int MOVERATE = 300;
	private int distance = 0; // the distance need to limit the time to
								// invalidate
	private float startAngle = 0;
	private int speed = 0;
	private int movedDistance = 0;// count if we already reach the goal,
	// and erase when we get new goal
	private float[] center = null;
	private float radius = 0;  //handle the bad touch , to forbid it 
	
	private long timestamp=0;   //we should control the speed we detect
	private float lastE1Angle=0;
	
	GestureDetector detector=null;

	public PieChart(Context context, RectF oval, float[] rates) {
		super(context);
		mPaints = new Paint();
		mPaints.setAntiAlias(true);
		mPaints.setStyle(Paint.Style.FILL);
		this.oval = oval;
		this.mSweeps = rates.clone();
		center=new float[]{oval.centerX(),oval.centerY()};
		radius=oval.height()<oval.width() ? oval.height()/2 : oval.width()/2;
		for (int i = 0; i < mSweeps.length; i++) {
			mSweeps[i] *= 360;
		}
		Logger.global.setLevel(Level.FINE);
		setFocusable(true);
		setFocusableInTouchMode(true);
		
		
		detector=new GestureDetector(getPieListener());
	}

	@Override
	public void setFocusable(boolean focusable) {
		// TODO Auto-generated method stub
		super.setFocusable(focusable);
	}

	protected void drawChart(Canvas canvas, RectF oval, float[] mSweeps,
			float startAngle) {
		// TODO if start >=360 start-360.use a count to remember the total
		// draw angle if needed
		while (startAngle > 360)
			startAngle -= 360;
		while (startAngle < 0)
			startAngle += 360;
		final int COLORDIFF = Math.abs((COLORRANGE) / mSweeps.length);
		for (int i = 0; i < mSweeps.length; i++) {
			int color = COLORRANGE + COLORDIFF * i;
			mPaints.setColor(color);
			canvas.drawArc(oval, startAngle, mSweeps[i], true, mPaints);
			startAngle += mSweeps[i];
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		if (speed == 0) {// initial
			drawChart(canvas, oval, mSweeps, startAngle);
		} else {// need move
			startAngle += speed;
			drawChart(canvas, oval, mSweeps, startAngle);
			movedDistance += Math.abs(speed);
			if (movedDistance < distance) {
				invalidate();
			}else{//finish move,reset to the original
				speed=0;
				movedDistance=0;
				distance=0;
			}
		}
	}
	

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		System.out.println("this is onTouchEvent"+"is focused"+isFocused());
		Logger.global.info("is focused? :"+isFocused());
		return detector.onTouchEvent(event);     //this is using onFling
	}


	private class PieGesturesListener implements OnGestureListener {
		/**
		 * we must add this to send msg to detector
		 */

		@Override
		public boolean onDown(MotionEvent e) {
			System.out.println("test if called onDown");
			
			/***
			 * here we need to set zero to the onsroll method to prevent 
			 * suddenly jump to another scroll
			 */
			timestamp=0;
			lastE1Angle=0;
			return true;
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2,
				float velocityX, float velocityY) {
			System.out.println("test if called onFling");
			System.out.println("speed:" + velocityX + "," + velocityY);
			System.out.println("Coordinate e1:" + e1.getX() + ","
					+ e1.getY());
			/*
			 * System.out.println("e1 size:"+e1.getSize());
			 * System.out.println("Orientation e1:"+e1.getOrientation());
			 * System
			 * .out.println("Coordinate p e1:"+e1.getXPrecision()+","+e1
			 * .getYPrecision());
			 * System.out.println("Coordinate e2:"+e2.getX()+","+e2.getY());
			 * System.out.println("e2 size:"+e2.getSize());
			 * System.out.println("Orientation e2:"+e2.getOrientation());
			 * System
			 * .out.println("Coordinate p e2:"+e2.getXPrecision()+","+e2
			 * .getYPrecision());
			 */
			// attention: we use this to calculate the direction.notice that
			// the Y's coordination is upside down compared to the normal
			// coordination
			float[] vtr = { e1.getX() * e1.getXPrecision() - center[0],
					-(e1.getY() * e1.getYPrecision() - center[1]) };
			float[] tanVtr = new float[2];
			// Calculate the clockwise vector
			if (vtr[0] > 0 && vtr[1] > 0) {// y=-x*x1/y1
				tanVtr[0] = 1;
				tanVtr[1] = -vtr[0] / vtr[1];
			} else if (vtr[0] < 0 && vtr[1] > 0) {
				tanVtr[0] = 1;
				tanVtr[1] = -vtr[0] / vtr[1];
			} else if (vtr[0] < 0 && vtr[1] < 0) {
				tanVtr[0] = -1;
				tanVtr[1] = vtr[0] / vtr[1];
			} else {
				tanVtr[0] = -1;
				tanVtr[1] = vtr[0] / vtr[1];
			}
			System.out.println("tanVtr" + tanVtr[0] + "," + tanVtr[1]);
			distance = (int) (1.1*(Math.sqrt(((e1.getX() - e2.getX())
					* (e1.getX() - e2.getX()) + (e1.getY() - e2.getY())
					* (e1.getY() - e2.getY())))));
			double totalVelocity = Math
					.sqrt((velocityX * velocityX + velocityY * velocityY));
			totalVelocity = totalVelocity > 4000 ? 4000 : totalVelocity; // control
																			// the
																			// max
																			// speed
			totalVelocity = totalVelocity / MOVERATE;// control the move
														// speed
			// attention: we use this to calculate the direction.notice that
			// the velocityY's coordination is upside down compared to the
			// normal coordination
			speed = (int) ((velocityX * tanVtr[0] + (-velocityY)
					* tanVtr[1]) > 0 ? totalVelocity : -totalVelocity);
			
			if((vtr[0]*vtr[0]+vtr[1]*vtr[1])<(radius*radius/16)){
				speed=0;
				distance=0;
			}
			PieChart.this.invalidate();
			// TODO watch out this object
			return true;
		}

		@Override
		public void onLongPress(MotionEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			long timeNow=System.currentTimeMillis();
			float[] NorVtr = { 1, 0 };

			if(timestamp==0){//first time init
				timestamp=timeNow;
				
				float[] e1Vtr = {
						e1.getX() * e1.getXPrecision() - center[0],
						(e1.getY() * e1.getYPrecision() - center[1]) };
				double temp = (NorVtr[0] * e1Vtr[0] + NorVtr[1] * e1Vtr[1])
						/ Math.sqrt((e1Vtr[0] * e1Vtr[0] + e1Vtr[1]
								* e1Vtr[1]));
				float e1Angle = (float) ((180 * Math.acos(temp)) / Math.PI);
				e1Angle = (e1Vtr[1] > 0 ? e1Angle : -e1Angle);
				
				lastE1Angle=e1Angle;
				
			}
			else{
				if ((timeNow - timestamp) > 100) {
					/*
					 * at this time the speed abs vaule may as same as distance
					 * and the distance is the between angle,and the speed to
					 * handle the dirction
					 */
					System.out.println("test if called onScroll");

					float[] e2Vtr = {
							e2.getX() * e2.getXPrecision() - center[0],
							(e2.getY() * e2.getYPrecision() - center[1]) };
					// now we need to calculate each vector's angle to the
					// normal one
					double temp = (NorVtr[0] * e2Vtr[0] + NorVtr[1] * e2Vtr[1])
							/ Math.sqrt((e2Vtr[0] * e2Vtr[0] + e2Vtr[1]
									* e2Vtr[1]));
					float e2Angle = (float) ((180 * Math.acos(temp)) / Math.PI);
					e2Angle = e2Vtr[1] > 0 ? e2Angle : -e2Angle;
					speed = (int) (e2Angle - lastE1Angle);
					distance = Math.abs(speed);
					if((e2Vtr[0]*e2Vtr[0]+e2Vtr[1]*e2Vtr[1])<(radius*radius/16)){
						speed=0;
						distance=0;
					}
					lastE1Angle=e2Angle;
					timestamp=System.currentTimeMillis();
					PieChart.this.invalidate();
				}
			}
			return true;
		}

		@Override
		public void onShowPress(MotionEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// TODO Auto-generated method stub
			System.out.println("test if called onSingleTapUp");
			return false;
		}
	}

	public OnGestureListener getPieListener(){
		return new PieGesturesListener();
	}
}
